﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using SGP;

namespace AnimationEditor
{
    public partial class Form1 : Form
    {
        bool looping;

        bool AnimLoop = false;
        bool Play = false;
        float m_fTimeWaited = 0.0f;
        float totalTimer = 0.0f;

        bool mouseIsPressed = false;
        int SpriteSheetID = -1;
        //string SpritePath;
        string SpriteName;
        string SystemPath;
        Bitmap SpriteSheetBM;

        enum ToolState { ANCHOR, DRAW, COLL };
        short CurrTool = (int)ToolState.DRAW;

        // Game time
        float m_fTimer = 0;

        // FPS
        int m_nFPS = 60;
        int m_nFrames = 0;
        float m_fFPSTimer = 0.0f;

        bool Flipped = false;

        Frame tmpF;

        List<Animation> animations = new List<Animation>();
        Animation tmpA;

        int CurrFrame = 0;
        int CurrAnim = 0;

        public bool Looping
        {
            get { return looping; }
            set { looping = value; }
        }

        CSGP_Direct3D DX;
        CSGP_TextureManager TM;

        // Marquee
        Point MarqueeDown = new Point(-1, -1);
        Point MarqueeUp = new Point(-1, -1);

        Point MarqueeDownColl = new Point(-1, -1);
        Point MarqueeUpColl = new Point(-1, -1);

        Rectangle EmptyRect = new Rectangle(0, 0, 0, 0);
        Point EmptyPoint = new Point(0, 0);
        string pos;

        enum MouseState { NORMAL, CROSS, ANCHOR, ERROR };
        int cursor = (int)MouseState.NORMAL;

        public Form1()
        {
            InitializeComponent();
            looping = true;

            DX = CSGP_Direct3D.GetInstance();
            TM = CSGP_TextureManager.GetInstance();

            DX.Initialize(CurrFramePanel, false);
            TM.Initialize(DX.Device, DX.Sprite);

            DX.AddRenderTarget(CurrFramePanel);
            DX.AddRenderTarget(SpriteSheetPanel);
            DX.AddRenderTarget(FramesList);
            DX.AddRenderTarget(AnimationListPanel);
            
            this.Focus();

            // Change the Current Working Directory out of the 'bin\Debug\' or 'bin\Release\' folders
            string dir = System.IO.Directory.GetCurrentDirectory();
            int index = dir.LastIndexOf("bin\\Debug");
            if (index != -1)
                dir = dir.Remove(index);
            index = dir.LastIndexOf("bin\\Release");
            if (index != -1)
                dir = dir.Remove(index);

            System.IO.Directory.SetCurrentDirectory(dir);

            DX.Resize(SpriteSheetPanel, SpriteSheetPanel.Size.Width - 16, SpriteSheetPanel.Size.Height - 16, false);

            // Store the Current Working Directory in the text box
            //txtWorkingDirectory.Text = System.IO.Directory.GetCurrentDirectory();
        }

        public void Update(float fElapsedTime)
        {
            // Update global timer
            m_fTimer += fElapsedTime;
            m_fTimeWaited += fElapsedTime;
            if(Play)
                totalTimer += fElapsedTime;

            // Update FPS
            ++m_nFrames;
            m_fFPSTimer += fElapsedTime;
            if (m_fFPSTimer > 1.0f)	// refresh every second
            {
                m_nFPS = m_nFrames;
                m_nFrames = 0;
                m_fFPSTimer = 0.0f;
            }

            if (Play)
            {
                if (m_fTimeWaited > animations[CurrAnim].frames[CurrFrame].Time)
                {
                    CurrFrame++;
                    m_fTimeWaited = 0.0f;

                    if (CurrFrame == animations[CurrAnim].frames.Count)
                    {
                        if (AnimLoop)
                            CurrFrame = 0;
                        else
                        {
                            CurrFrame--;
                            Play = false;
                            totalTimer = 0.0f;
                        }
                    }
                }
            }

            MousePos.Text = pos;
            FPSBox.Text = m_nFPS.ToString();
            TimeBox.Text = totalTimer.ToString();
        }

        public void Terminate()
        {
            if (SpriteSheetID != -1)
            {
                TM.UnloadTexture(SpriteSheetID);
                SpriteSheetID = -1;
            }

            TM.Terminate();
            DX.Terminate();
        }

        public void Render()
        {
            RenderSpriteSheet();
            RenderFramesList();
            RenderCurrFrame();
            RenderAnimationsList();
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            looping = false;
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
            looping = false;
        }

        private void RenderFramesList()
        {
            DX.Clear(FramesList, Color.White);
            DX.DeviceBegin();
            DX.SpriteBegin();

            if (animations.Count != 0)
            {
                for (int i = 0; i < animations[CurrAnim].frames.Count; i++)
                {
                    string text = "Frame ";
                    text += i + 1;
                    if (i == CurrFrame)
                        DX.DrawText(text, 10, ((i * 20) + 10) - FLVScroll.Value, Color.Green);
                    else
                        DX.DrawText(text, 10, ((i * 20) + 10) - FLVScroll.Value, Color.Black);
                }
            }

            

            DX.SpriteEnd();
            DX.DeviceEnd();
            DX.Present();
        }

        private void RenderAnimationsList()
        {
            DX.Clear(AnimationListPanel, Color.White);
            DX.DeviceBegin();
            DX.SpriteBegin();

            for (int i = 0; i < animations.Count; i++)
            {
                string name = "";
                name += i + 1;
                name += ": ";
                name += animations[i].Name;
                if (i == CurrAnim)
                    DX.DrawText(name, 10, ((i * 20) + 10) - ALVScroll.Value, Color.Green);
                else
                    DX.DrawText(name, 10, ((i * 20) + 10) - ALVScroll.Value, Color.Black);
            }

            DX.SpriteEnd();
            DX.DeviceEnd();
            DX.Present();
        }

        private void RenderCurrFrame()
        {
            DX.Clear(CurrFramePanel, Color.White);
            DX.DeviceBegin();
            DX.SpriteBegin();

            int CenterX = CurrFramePanel.Width / 2;
            int CenterY = CurrFramePanel.Height / 2;

            float SpriteScale = (float)SheetSizeNum.Value / 100.0f;

            /*Rectangle test = new Rectangle(MarqueeDown.X,
                                            MarqueeDown.Y,
                                            MarqueeUp.X,
                                            MarqueeUp.Y);*/

            if (animations.Count != 0)
            {
                if (animations[CurrAnim].frames.Count != 0)
                {
                    if (SpriteSheetID != -1 && animations[CurrAnim].frames[CurrFrame].DrawRect != EmptyRect)
                    {
                        if (Flipped == false)
                        {
                            TM.Draw(SpriteSheetID, (int)(CenterX - (animations[CurrAnim].frames[CurrFrame].AnchorPoint.X * SpriteScale)),
                            (int)(CenterY - (animations[CurrAnim].frames[CurrFrame].AnchorPoint.Y * SpriteScale)),
                            SpriteScale, SpriteScale, animations[CurrAnim].frames[CurrFrame].DrawRect);
                            if (animations[CurrAnim].frames[CurrFrame].CollRect == EmptyRect)
                            {
                                Rectangle drawRect = new Rectangle(MarqueeDownColl.X,
                                                        MarqueeDownColl.Y,
                                                            MarqueeUpColl.X - MarqueeDownColl.X, MarqueeUpColl.Y - MarqueeDownColl.Y);
                                DX.DrawHollowRect(drawRect, Color.Red, 2);
                            }
                            else
                            {
                                Rectangle drawRect = new Rectangle((int)(CenterX - ((animations[CurrAnim].frames[CurrFrame].AnchorPoint.X - animations[CurrAnim].frames[CurrFrame].CollRect.X) * SpriteScale)),
                                                                    (int)(CenterY - ((animations[CurrAnim].frames[CurrFrame].AnchorPoint.Y - animations[CurrAnim].frames[CurrFrame].CollRect.Y) * SpriteScale)),
                                                                    (int)(animations[CurrAnim].frames[CurrFrame].CollRect.Width * SpriteScale),
                                                                    (int)(animations[CurrAnim].frames[CurrFrame].CollRect.Height * SpriteScale));
                                DX.DrawHollowRect(drawRect, Color.Red, 2);
                            }

                            if (animations[CurrAnim].frames[CurrFrame].AnchorPoint != EmptyPoint)
                            {
                                Rectangle anchor = new Rectangle(CenterX,
                                                                 CenterY,
                                                                 4, 4);

                                DX.DrawRect(anchor, Color.Gold);
                            }
                        }

                        else
                        {
                            TM.Draw(SpriteSheetID, (int)(CenterX + (animations[CurrAnim].frames[CurrFrame].AnchorPoint.X * SpriteScale)),
                            (int)(CenterY - (animations[CurrAnim].frames[CurrFrame].AnchorPoint.Y * SpriteScale)),
                            -SpriteScale, SpriteScale, animations[CurrAnim].frames[CurrFrame].DrawRect);
                            if (animations[CurrAnim].frames[CurrFrame].CollRect == EmptyRect)
                            {
                                Rectangle drawRect = new Rectangle(MarqueeDownColl.X,
                                                        MarqueeDownColl.Y,
                                                            MarqueeUpColl.X - MarqueeDownColl.X, MarqueeUpColl.Y - MarqueeDownColl.Y);
                                DX.DrawHollowRect(drawRect, Color.Red, 2);
                            }
                            else
                            {
                                Rectangle drawRect = new Rectangle((int)(CenterX - ((animations[CurrAnim].frames[CurrFrame].AnchorPoint.X - animations[CurrAnim].frames[CurrFrame].CollRect.X) * SpriteScale)),
                                                                    (int)(CenterY - ((animations[CurrAnim].frames[CurrFrame].AnchorPoint.Y - animations[CurrAnim].frames[CurrFrame].CollRect.Y) * SpriteScale)),
                                                                    (int)(animations[CurrAnim].frames[CurrFrame].CollRect.Width * SpriteScale),
                                                                    (int)(animations[CurrAnim].frames[CurrFrame].CollRect.Height * SpriteScale));
                                DX.DrawHollowRect(drawRect, Color.Red, 2);
                            }

                            if (animations[CurrAnim].frames[CurrFrame].AnchorPoint != EmptyPoint)
                            {
                                Rectangle anchor = new Rectangle(CenterX,
                                                                 CenterY,
                                                                 4, 4);

                                DX.DrawRect(anchor, Color.Gold);
                            }

                        }
                    }
                }
            }

            DX.SpriteEnd();
            DX.DeviceEnd();
            DX.Present();
        }

        private void RenderSpriteSheet()
        {
            DX.Clear(SpriteSheetPanel, Color.White);
            DX.DeviceBegin();
            DX.SpriteBegin();

            float SpriteScale = (float)SheetSizeNum.Value / 100.0f;

            Point Offset = new Point(0, 0);
            Offset.X += (int)(SSHScroll.Value /** SpriteScale*/);
            Offset.Y += (int)(SSVScroll.Value /** SpriteScale*/);


            if (SpriteSheetID != -1)
            {
                TM.Draw(SpriteSheetID, 0 - Offset.X, 0 - Offset.Y, SpriteScale, SpriteScale);
                Rectangle drawRect = new Rectangle( (int)((MarqueeDown.X) * SpriteScale),
                                                    (int)((MarqueeDown.Y) * SpriteScale),
                                                    (int)((MarqueeUp.X - MarqueeDown.X) * SpriteScale),
                                                    (int)((MarqueeUp.Y - MarqueeDown.Y) * SpriteScale));
                DX.DrawHollowRect(drawRect, Color.Green, 2);
            }

            DX.SpriteEnd();
            DX.DeviceEnd();
            DX.Present();
        }

        private void importToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();

            if (DialogResult.OK == dlg.ShowDialog())
            {
                SpriteName = dlg.SafeFileName;
                SpriteSheetID = TM.LoadTexture(SystemPath + dlg.SafeFileName);
                SpriteSheetBM = new Bitmap(dlg.FileName);

                SSVScroll.Maximum = SpriteSheetBM.Size.Height;
                SSHScroll.Maximum = SpriteSheetBM.Size.Width;

                //Size s = new Size(SpriteSheetBM.Width, SpriteSheetBM.Height);
                //SpriteSheetPanel.AutoScrollMinSize = s;
                //DX.Resize(SpriteSheetPanel, false);
            }
        }

        private void radioButton1_CheckedChanged(object sender, EventArgs e)
        {
            if (AnchorTool.Checked == true)
                CurrTool = (int)ToolState.ANCHOR;
        }

        private void DrawTool_CheckedChanged(object sender, EventArgs e)
        {
            if (DrawTool.Checked == true)
                CurrTool = (int)ToolState.DRAW;
        }

        private void CollTool_CheckedChanged(object sender, EventArgs e)
        {
            if (CollTool.Checked == true)
                CurrTool = (int)ToolState.COLL;
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            Flipped = !Flipped;
        }

        private void SheetSizeNum_ValueChanged(object sender, EventArgs e)
        {
            if (SheetSizeNum.Value < 1)
                SheetSizeNum.Value = 1;

            float SpriteScale = (float)SheetSizeNum.Value / 100.0f;

            Size s = new Size((int)(SpriteSheetBM.Width * SpriteScale), (int)(SpriteSheetBM.Height * SpriteScale));
            SSVScroll.Maximum = s.Height;
            SSHScroll.Maximum = s.Width;
        }

        private void checkBox2_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox2.Checked == true)
            {
                animations[CurrAnim].Loop = AnimLoop = true;
                AnimationIsLooping.Checked = true;
            }
            else
            {
                animations[CurrAnim].Loop = AnimLoop = false;
                AnimationIsLooping.Checked = false;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Play = !Play;
            if (Play)
            {
                CurrFrame = 0;
                totalTimer = 0.0f;
            }
        }

        private void SpriteSheetPanel_MouseDown(object sender, MouseEventArgs e)
        {
            if (SpriteSheetID != -1 && CurrTool == (int)ToolState.DRAW)
            {
                MarqueeDown.X = e.Location.X;
                MarqueeDown.Y = e.Location.Y;
                MarqueeUp.X = MarqueeDown.X;
                MarqueeUp.Y = MarqueeDown.Y;
                mouseIsPressed = true;
            }
        }

        private void SpriteSheetPanel_MouseMove(object sender, MouseEventArgs e)
        {
            if (mouseIsPressed == true)
            {
                MarqueeUp.X = e.Location.X;
                MarqueeUp.Y = e.Location.Y;
            }

            Point offset = new Point(e.Location.X + SpriteSheetPanel.AutoScrollPosition.X,
                                    e.Location.Y + SpriteSheetPanel.AutoScrollPosition.Y);
            pos = offset.ToString();
        }

        private void SpriteSheetPanel_MouseUp(object sender, MouseEventArgs e)
        {
            if (animations[CurrAnim].frames.Count != 0 && CurrFrame != -1 && SpriteSheetID != -1 && CurrTool == (int)ToolState.DRAW)
            {
                mouseIsPressed = false;
                Rectangle TMPR = new Rectangle(MarqueeDown.X + SSHScroll.Value,
                                                MarqueeDown.Y + SSVScroll.Value,
                                                    MarqueeUp.X - MarqueeDown.X, MarqueeUp.Y - MarqueeDown.Y);

                if (TMPR.X < 0)
                    TMPR.X = 0;
                if (TMPR.Y < 0)
                    TMPR.Y = 0;
                if (TMPR.Width < 0)
                    TMPR.Width = 0;
                if (TMPR.Height < 0)
                    TMPR.Height = 0;

                animations[CurrAnim].frames[CurrFrame].DrawRect = TMPR;

                DrawL.Value = animations[CurrAnim].frames[CurrFrame].DrawRect.Left;
                DrawT.Value = animations[CurrAnim].frames[CurrFrame].DrawRect.Top;
                DrawR.Value = animations[CurrAnim].frames[CurrFrame].DrawRect.Width;
                DrawB.Value = animations[CurrAnim].frames[CurrFrame].DrawRect.Height;
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (animations.Count != 0)
            {
                // New Frame
                tmpF = new Frame();
                tmpF.FrameNumber = animations[CurrAnim].frames.Count;
                CurrFrame = animations[CurrAnim].frames.Count;
                animations[CurrAnim].frames.Add(tmpF);


                int s = (animations[CurrAnim].frames.Count * 20) + 10;
                if (s - 140 > 0)
                    FLVScroll.Maximum = s - 140;
                else
                    FLVScroll.Maximum = s;

                if (animations[CurrAnim].frames.Count != 0)
                    FLVScroll.LargeChange = s / animations[CurrAnim].frames.Count;

                DrawL.Value = 0;
                DrawT.Value = 0;
                DrawR.Value = 0;
                DrawB.Value = 0;

                CollL.Value = 0;
                CollT.Value = 0;
                CollR.Value = 0;
                CollB.Value = 0;

                AnchorX.Value = 0;
                AnchorY.Value = 0;

                frameTrigger.Text = "";
                FrameTime.Value = (decimal)0.00;
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            // New Animation
            tmpA = new Animation();
            CurrAnim = animations.Count;
            animations.Add(tmpA);

            int s = (animations.Count * 20) + 10;
            if (s - 140 > 0)
                ALVScroll.Maximum = s - 140;
            else
                ALVScroll.Maximum = s;

            if (animations.Count != 0)
                ALVScroll.LargeChange = s / animations.Count;

            DrawL.Value = 0;
            DrawT.Value = 0;
            DrawR.Value = 0;
            DrawB.Value = 0;

            CollL.Value = 0;
            CollT.Value = 0;
            CollR.Value = 0;
            CollB.Value = 0;

            AnchorX.Value = 0;
            AnchorY.Value = 0;

            frameTrigger.Text = "";
            FrameTime.Value = (decimal)0.00;
        }

        private void FramesList_MouseClick(object sender, MouseEventArgs e)
        {
            if (animations[CurrAnim].frames.Count != 0)
            {
                for (int i = 0, j = animations[CurrAnim].frames.Count; i < animations[CurrAnim].frames.Count; i++, --j)
                {
                    if (e.Location.Y + FLVScroll.Value < ((j * 20) + 10))
                    {
                        CurrFrame = j - 1;
                    }
                }

                DrawL.Value = animations[CurrAnim].frames[CurrFrame].DrawRect.Left;
                DrawT.Value = animations[CurrAnim].frames[CurrFrame].DrawRect.Top;
                DrawR.Value = animations[CurrAnim].frames[CurrFrame].DrawRect.Width;
                DrawB.Value = animations[CurrAnim].frames[CurrFrame].DrawRect.Height;

                CollL.Value = animations[CurrAnim].frames[CurrFrame].CollRect.Left;
                CollT.Value = animations[CurrAnim].frames[CurrFrame].CollRect.Top;
                CollR.Value = animations[CurrAnim].frames[CurrFrame].CollRect.Width;
                CollB.Value = animations[CurrAnim].frames[CurrFrame].CollRect.Height;

                AnchorX.Value = animations[CurrAnim].frames[CurrFrame].AnchorPoint.X;
                AnchorY.Value = animations[CurrAnim].frames[CurrFrame].AnchorPoint.Y;

                frameTrigger.Text = animations[CurrAnim].frames[CurrFrame].Trigger;
                FrameTime.Value = (decimal)animations[CurrAnim].frames[CurrFrame].Time;
            }
        }

        private void AnimationListPanel_MouseClick(object sender, MouseEventArgs e)
        {
            if (animations.Count != 0)
            {
                for (int i = 0, j = animations.Count; i < animations.Count; i++, --j)
                {
                    if (e.Location.Y + ALVScroll.Value < ((j * 20) + 10))
                    {
                        CurrAnim = j - 1;
                    }
                }
                CurrFrame = 0;
                if (animations[CurrAnim].frames.Count != 0)
                {
                    DrawL.Value = animations[CurrAnim].frames[CurrFrame].DrawRect.Left;
                    DrawT.Value = animations[CurrAnim].frames[CurrFrame].DrawRect.Top;
                    DrawR.Value = animations[CurrAnim].frames[CurrFrame].DrawRect.Width;
                    DrawB.Value = animations[CurrAnim].frames[CurrFrame].DrawRect.Height;

                    CollL.Value = animations[CurrAnim].frames[CurrFrame].CollRect.Left;
                    CollT.Value = animations[CurrAnim].frames[CurrFrame].CollRect.Top;
                    CollR.Value = animations[CurrAnim].frames[CurrFrame].CollRect.Width;
                    CollB.Value = animations[CurrAnim].frames[CurrFrame].CollRect.Height;

                    AnchorX.Value = animations[CurrAnim].frames[CurrFrame].AnchorPoint.X;
                    AnchorY.Value = animations[CurrAnim].frames[CurrFrame].AnchorPoint.Y;

                    frameTrigger.Text = animations[CurrAnim].frames[CurrFrame].Trigger;
                    FrameTime.Value = (decimal)animations[CurrAnim].frames[CurrFrame].Time;
                }
                AnimNameBox.Text = animations[CurrAnim].Name;
                if (animations[CurrAnim].Loop == true)
                    AnimationIsLooping.Checked = true;
                else
                    AnimationIsLooping.Checked = false;
            }
        }

        private void FramesList_MouseMove(object sender, MouseEventArgs e)
        {
            Point offset = new Point(e.Location.X + FramesList.AutoScrollPosition.X,
                                    e.Location.Y + FramesList.AutoScrollPosition.Y);
            pos = offset.ToString();
        }

        private void CurrFramePanel_MouseDown(object sender, MouseEventArgs e)
        {
            if (CurrTool == (int)ToolState.COLL && SpriteSheetID != -1 && animations[CurrAnim].frames.Count != 0)
            {
                MarqueeDownColl.X = e.Location.X;
                MarqueeDownColl.Y = e.Location.Y;
                MarqueeUpColl.X = MarqueeDownColl.X;
                MarqueeUpColl.Y = MarqueeDownColl.Y;
                mouseIsPressed = true;
            }
        }

        private void CurrFramePanel_MouseMove(object sender, MouseEventArgs e)
        {
            if (mouseIsPressed == true)
            {
                MarqueeUpColl.X = e.Location.X;
                MarqueeUpColl.Y = e.Location.Y;
            }

            Point offset = new Point(e.Location.X + CurrFramePanel.AutoScrollPosition.X,
                                    e.Location.Y + CurrFramePanel.AutoScrollPosition.Y);
            pos = offset.ToString();
        }

        private void CurrFramePanel_MouseUp(object sender, MouseEventArgs e)
        {
            if (animations[CurrAnim].frames.Count != 0 && CurrFrame != -1 && SpriteSheetID != -1 && CurrTool == (int)ToolState.COLL)
            {
                int CenterX = (CurrFramePanel.Width / 2) - animations[CurrAnim].frames[CurrFrame].AnchorPoint.X;
                int CenterY = (CurrFramePanel.Height / 2) - animations[CurrAnim].frames[CurrFrame].AnchorPoint.Y;

                mouseIsPressed = false;
                Rectangle TMPR = new Rectangle(MarqueeDownColl.X - CenterX,
                                                MarqueeDownColl.Y - CenterY,
                                                    MarqueeUpColl.X - MarqueeDownColl.X, MarqueeUpColl.Y - MarqueeDownColl.Y);

                if (TMPR.X < 0)
                    TMPR.X = 0;
                if (TMPR.Y < 0)
                    TMPR.Y = 0;

                animations[CurrAnim].frames[CurrFrame].CollRect = TMPR;

                CollL.Value = animations[CurrAnim].frames[CurrFrame].CollRect.Left;
                CollT.Value = animations[CurrAnim].frames[CurrFrame].CollRect.Top;
                CollR.Value = animations[CurrAnim].frames[CurrFrame].CollRect.Width;
                CollB.Value = animations[CurrAnim].frames[CurrFrame].CollRect.Height;
            }
        }

        private void CurrFramePanel_MouseClick(object sender, MouseEventArgs e)
        {
            int CenterX = CurrFramePanel.Width / 2;
            int CenterY = CurrFramePanel.Height / 2;

            if (CurrTool == (int)ToolState.ANCHOR)
            {
                Point p = new Point(e.Location.X - CenterX, e.Location.Y - CenterY);
                if (p.X < 0)
                    p.X = 0;
                if (p.Y < 0)
                    p.Y = 0;

                animations[CurrAnim].frames[CurrFrame].AnchorPoint = p;

                AnchorX.Value = animations[CurrAnim].frames[CurrFrame].AnchorPoint.X;
                AnchorY.Value = animations[CurrAnim].frames[CurrFrame].AnchorPoint.Y;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////
        /// Fine Tuning of Current Frame Info
        ///////////////////////////////////////////////////////////////////////////////////

        // Draw Rect
        private void DrawL_ValueChanged(object sender, EventArgs e)
        {
            if (animations[CurrAnim].frames.Count != 0)
            {
                Rectangle r = new Rectangle((int)DrawL.Value, animations[CurrAnim].frames[CurrFrame].DrawRect.Y,
                                            animations[CurrAnim].frames[CurrFrame].DrawRect.Width, animations[CurrAnim].frames[CurrFrame].DrawRect.Height);
                animations[CurrAnim].frames[CurrFrame].DrawRect = r;
            }
        }

        private void DrawT_ValueChanged(object sender, EventArgs e)
        {
            if (animations[CurrAnim].frames.Count != 0)
            {
                Rectangle r = new Rectangle(animations[CurrAnim].frames[CurrFrame].DrawRect.X, (int)DrawT.Value,
                                            animations[CurrAnim].frames[CurrFrame].DrawRect.Width, animations[CurrAnim].frames[CurrFrame].DrawRect.Height);
                animations[CurrAnim].frames[CurrFrame].DrawRect = r;
            }
        }

        private void DrawR_ValueChanged(object sender, EventArgs e)
        {
            if (animations[CurrAnim].frames.Count != 0)
            {
                Rectangle r = new Rectangle(animations[CurrAnim].frames[CurrFrame].DrawRect.X, animations[CurrAnim].frames[CurrFrame].DrawRect.Y,
                                            (int)DrawR.Value, animations[CurrAnim].frames[CurrFrame].DrawRect.Height);
                animations[CurrAnim].frames[CurrFrame].DrawRect = r;
            }
        }

        private void DrawB_ValueChanged(object sender, EventArgs e)
        {
            if (animations[CurrAnim].frames.Count != 0)
            {
                Rectangle r = new Rectangle(animations[CurrAnim].frames[CurrFrame].DrawRect.X, animations[CurrAnim].frames[CurrFrame].DrawRect.Y,
                                            animations[CurrAnim].frames[CurrFrame].DrawRect.Width, (int)DrawB.Value);
                animations[CurrAnim].frames[CurrFrame].DrawRect = r;
            }
        }

        // Collision Rect
        private void CollL_ValueChanged(object sender, EventArgs e)
        {
            if (animations[CurrAnim].frames.Count != 0)
            {
                Rectangle r = new Rectangle((int)CollL.Value, animations[CurrAnim].frames[CurrFrame].CollRect.Y,
                                            animations[CurrAnim].frames[CurrFrame].CollRect.Width, animations[CurrAnim].frames[CurrFrame].CollRect.Height);
                animations[CurrAnim].frames[CurrFrame].CollRect = r;
            }
        }

        private void CollT_ValueChanged(object sender, EventArgs e)
        {
            if (animations[CurrAnim].frames.Count != 0)
            {
                Rectangle r = new Rectangle(animations[CurrAnim].frames[CurrFrame].CollRect.X, (int)CollT.Value,
                                            animations[CurrAnim].frames[CurrFrame].CollRect.Width, animations[CurrAnim].frames[CurrFrame].CollRect.Height);
                animations[CurrAnim].frames[CurrFrame].CollRect = r;
            }
        }

        private void CollR_ValueChanged(object sender, EventArgs e)
        {
            if (animations[CurrAnim].frames.Count != 0)
            {
                Rectangle r = new Rectangle(animations[CurrAnim].frames[CurrFrame].CollRect.X, animations[CurrAnim].frames[CurrFrame].CollRect.Y,
                                            (int)CollR.Value, animations[CurrAnim].frames[CurrFrame].CollRect.Height);
                animations[CurrAnim].frames[CurrFrame].CollRect = r;
            }
        }

        private void CollB_ValueChanged(object sender, EventArgs e)
        {
            if (animations[CurrAnim].frames.Count != 0)
            {
                Rectangle r = new Rectangle(animations[CurrAnim].frames[CurrFrame].CollRect.X, animations[CurrAnim].frames[CurrFrame].CollRect.Y,
                                            animations[CurrAnim].frames[CurrFrame].CollRect.Width, (int)CollB.Value);
                animations[CurrAnim].frames[CurrFrame].CollRect = r;
            }
        }

        // Anchor Point
        private void AnchorX_ValueChanged(object sender, EventArgs e)
        {
            if (animations[CurrAnim].frames.Count != 0)
            {
                Point n = new Point((int)AnchorX.Value, animations[CurrAnim].frames[CurrFrame].AnchorPoint.Y);
                animations[CurrAnim].frames[CurrFrame].AnchorPoint = n;
            }
        }

        private void AnchorY_ValueChanged(object sender, EventArgs e)
        {
            if (animations[CurrAnim].frames.Count != 0)
            {
                Point n = new Point(animations[CurrAnim].frames[CurrFrame].AnchorPoint.X, (int)AnchorY.Value);
                animations[CurrAnim].frames[CurrFrame].AnchorPoint = n;
            }
        }

        // Trigger
        private void frameTrigger_TextChanged(object sender, EventArgs e)
        {
            if (animations[CurrAnim].frames.Count != 0)
            {
                animations[CurrAnim].frames[CurrFrame].Trigger = frameTrigger.Text;
            }
        }

        // Frame Time
        private void FrameTime_ValueChanged(object sender, EventArgs e)
        {
            if (animations[CurrAnim].frames.Count != 0)
            {
                animations[CurrAnim].frames[CurrFrame].Time = (float)FrameTime.Value;
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (animations[CurrAnim].frames.Count != 0 && CurrFrame >= 0)
            {
                if (CurrFrame + 1 == animations[CurrAnim].frames.Count)
                {
                    animations[CurrAnim].frames.RemoveAt(CurrFrame);
                    CurrFrame--;
                }
                else
                    animations[CurrAnim].frames.RemoveAt(CurrFrame);
            }
        }

        private void button5_Click(object sender, EventArgs e)
        {
            if (animations.Count != 0 && CurrAnim >= 0)
            {
                if (CurrAnim + 1 == animations.Count)
                {
                    animations.RemoveAt(CurrAnim);
                    CurrAnim--;
                }
                else
                    animations.RemoveAt(CurrAnim);
            }
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.DefaultExt = ".xml";

            for (int k = 0; k < animations.Count; k++)
            {
                if (animations[k].Name == "<EMPTY>")
                {
                    MessageBox.Show("No animations can be named: <EMPTY>",
                                    "Critical Error",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Exclamation,
                                    MessageBoxDefaultButton.Button1);
                    return;
                }

                for (int l = 0; l < animations.Count; l++)
                {
                    if (l != k && animations[l].Name == animations[k].Name)
                    {
                        string errorMsg = "Animations cannot have duplicate names\n";
                        errorMsg += k + 1;
                        errorMsg += " & ";
                        errorMsg += l + 1;
                        errorMsg += ": ";
                        errorMsg += animations[k].Name;

                        MessageBox.Show(errorMsg,
                                    "Critical Error",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Exclamation,
                                    MessageBoxDefaultButton.Button1);
                        return;
                    }
                }
            }

            if (DialogResult.OK == dlg.ShowDialog())
            {

                XmlWriterSettings settings = new XmlWriterSettings();
                XmlWriter w = XmlWriter.Create( dlg.FileName,settings );
                //w.Formatting = Formatting.Indented;

                w.WriteStartDocument();
                w.WriteStartElement("Sheet");

                w.WriteStartElement("FileName");
                w.WriteAttributeString("Name", SpriteName);
                w.WriteEndElement();

                w.WriteStartElement("Animations");
                for (int j = 0; j < animations.Count; j++)
                {
                    w.WriteStartElement("Animation");
                    w.WriteAttributeString("Name", animations[j].Name);
                    if (animations[j].Loop == true)
                        w.WriteAttributeString("IsLooping", "1");
                    else
                        w.WriteAttributeString("IsLooping", "0");

                    w.WriteStartElement("Frames");
                    for (int i = 0; i < animations[j].frames.Count; i++)
                    {
                        w.WriteStartElement("Frame");

                        w.WriteAttributeString("CollW", animations[j].frames[i].CollRect.Width.ToString());
                        w.WriteAttributeString("CollH", animations[j].frames[i].CollRect.Height.ToString());
                        w.WriteAttributeString("CollY", animations[j].frames[i].CollRect.Y.ToString());
                        w.WriteAttributeString("CollX", animations[j].frames[i].CollRect.X.ToString());

                        w.WriteAttributeString("DrawW", animations[j].frames[i].DrawRect.Width.ToString());
                        w.WriteAttributeString("DrawH", animations[j].frames[i].DrawRect.Height.ToString());
                        w.WriteAttributeString("DrawY", animations[j].frames[i].DrawRect.Y.ToString());
                        w.WriteAttributeString("DrawX", animations[j].frames[i].DrawRect.X.ToString());

                        w.WriteAttributeString("Trigger", animations[j].frames[i].Trigger);

                        w.WriteAttributeString("Time", animations[j].frames[i].Time.ToString());

                        w.WriteAttributeString("AnchorY", animations[j].frames[i].AnchorPoint.Y.ToString());
                        w.WriteAttributeString("AnchorX", animations[j].frames[i].AnchorPoint.X.ToString());

                        w.WriteAttributeString("FrameNumber", i.ToString());

                        w.WriteEndElement();
                    }
                    w.WriteEndElement();
                    w.WriteEndElement();
                }
                w.WriteEndElement();
                w.WriteEndElement();
                
                w.WriteEndDocument();
                w.Flush();
            }
        }

        private void loadToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            if (DialogResult.OK == dlg.ShowDialog())
            {
                animations.Clear();
                CurrAnim = CurrTool = 0;

                XElement xRoot = XElement.Load(dlg.FileName);

                XElement xFileName = xRoot.Element("FileName");
                XAttribute xImageName = xFileName.Attribute("Name");

                if (SpriteSheetID != -1)
                {
                    TM.UnloadTexture(SpriteSheetID);
                    SpriteSheetID = TM.LoadTexture(SystemPath + xImageName.Value);
                    SpriteSheetBM = new Bitmap(SystemPath + xImageName.Value);
                }
                else
                {
                    SpriteSheetID = TM.LoadTexture(SystemPath + xImageName.Value);
                    SpriteSheetBM = new Bitmap(SystemPath + xImageName.Value);
                }

                SSVScroll.Maximum = SpriteSheetBM.Size.Height;
                SSHScroll.Maximum = SpriteSheetBM.Size.Width;

                SpriteName = xImageName.Value;

                XElement xAnimations = xRoot.Element("Animations");

                IEnumerable<XElement> xAnims = xAnimations.Elements();

                foreach (XElement xAnimation in xAnims)
                {
                    tmpA = new Animation();

                    XAttribute xName = xAnimation.Attribute("Name");
                    tmpA.Name = xName.Value;

                    XAttribute xIsLooping = xAnimation.Attribute("IsLooping");
                    if (Convert.ToInt32(xIsLooping.Value) != 0)
                        tmpA.Loop = true;
                    else
                        tmpA.Loop = false;

                    XElement xFrames = xAnimation.Element("Frames");

                    IEnumerable<XElement> xFrameF = xFrames.Elements();
                    foreach (XElement xFrame in xFrameF)
                    {
                        Frame tmpF = new Frame();

                        XAttribute xCollW = xFrame.Attribute("CollW");
                        
                        XAttribute xCollH = xFrame.Attribute("CollH");
                        XAttribute xCollY = xFrame.Attribute("CollY");
                        XAttribute xCollX = xFrame.Attribute("CollX");

                        XAttribute xDrawW = xFrame.Attribute("DrawW");
                        XAttribute xDrawH = xFrame.Attribute("DrawH");
                        XAttribute xDrawY = xFrame.Attribute("DrawY");
                        XAttribute xDrawX = xFrame.Attribute("DrawX");

                        XAttribute xTrigger = xFrame.Attribute("Trigger");

                        XAttribute xTime = xFrame.Attribute("Time");

                        XAttribute xAnchorY = xFrame.Attribute("AnchorX");
                        XAttribute xAnchorX = xFrame.Attribute("AnchorY");

                        XAttribute xFrameNumber = xFrame.Attribute("FrameNumber");

                        Rectangle d = new Rectangle(Convert.ToInt32(xDrawX.Value), Convert.ToInt32(xDrawY.Value), Convert.ToInt32(xDrawW.Value), Convert.ToInt32(xDrawH.Value));
                        Rectangle c = new Rectangle(Convert.ToInt32(xCollX.Value), Convert.ToInt32(xCollY.Value), Convert.ToInt32(xCollW.Value), Convert.ToInt32(xCollH.Value));

                        Point a = new Point(Convert.ToInt32(xAnchorY.Value), Convert.ToInt32(xAnchorX.Value));

                        tmpF.DrawRect = d;
                        tmpF.CollRect = c;
                        tmpF.Trigger = Convert.ToString(xTrigger.Value);
                        tmpF.Time = (float)Convert.ToDouble(xTime.Value);
                        tmpF.AnchorPoint = a;
                        tmpF.FrameNumber = Convert.ToInt32(xFrameNumber.Value);

                        tmpA.frames.Add(tmpF);
                    }
                    animations.Add(tmpA);
                }

                DrawL.Value = animations[CurrAnim].frames[CurrFrame].DrawRect.Left;
                DrawT.Value = animations[CurrAnim].frames[CurrFrame].DrawRect.Top;
                DrawR.Value = animations[CurrAnim].frames[CurrFrame].DrawRect.Width;
                DrawB.Value = animations[CurrAnim].frames[CurrFrame].DrawRect.Height;

                CollL.Value = animations[CurrAnim].frames[CurrFrame].CollRect.Left;
                CollT.Value = animations[CurrAnim].frames[CurrFrame].CollRect.Top;
                CollR.Value = animations[CurrAnim].frames[CurrFrame].CollRect.Width;
                CollB.Value = animations[CurrAnim].frames[CurrFrame].CollRect.Height;

                AnchorX.Value = animations[CurrAnim].frames[CurrFrame].AnchorPoint.X;
                AnchorY.Value = animations[CurrAnim].frames[CurrFrame].AnchorPoint.Y;

                frameTrigger.Text = animations[CurrAnim].frames[CurrFrame].Trigger;
                FrameTime.Value = (decimal)animations[CurrAnim].frames[CurrFrame].Time;

                AnimNameBox.Text = animations[CurrAnim].Name;
                checkBox2.Checked = AnimationIsLooping.Checked = animations[CurrAnim].Loop;
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            FolderBrowserDialog dlg = new FolderBrowserDialog();
            if (DialogResult.OK == dlg.ShowDialog())
                SystemPath = dlg.SelectedPath + "/";

            //this.TopMost = true;
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (animations[CurrAnim].frames.Count != 0)
            {
                switch (e.KeyCode)
                {
                    case Keys.Up:
                        if (CurrFrame > 0)
                            CurrFrame--;
                        break;
                    case Keys.Down:
                        if (CurrFrame + 1 < animations[CurrAnim].frames.Count)
                            CurrFrame++;
                        break;
                }
            }
        }

        private void AnimNameBox_TextChanged(object sender, EventArgs e)
        {
            animations[CurrAnim].Name = AnimNameBox.Text;
        }

        private void AnimationIsLooping_CheckedChanged(object sender, EventArgs e)
        {
            if (AnimationIsLooping.Checked == true)
            {
                animations[CurrAnim].Loop = AnimLoop = true;
                checkBox2.Checked = true;
            }
            else
            {
                animations[CurrAnim].Loop = AnimLoop = false;
                checkBox2.Checked = false;
            }
        }

        private void SpriteSheetPanel_MouseEnter(object sender, EventArgs e)
        {
            if (CurrTool == (int)ToolState.DRAW)
                SpriteSheetPanel.Cursor = Cursors.Arrow;
            else if( CurrTool == (int)ToolState.ANCHOR || CurrTool == (int)ToolState.COLL)
                SpriteSheetPanel.Cursor = Cursors.No;
        }

        private void CurrFramePanel_MouseEnter(object sender, EventArgs e)
        {
            if (CurrTool == (int)ToolState.DRAW)
                CurrFramePanel.Cursor = Cursors.No;
            else if (CurrTool == (int)ToolState.ANCHOR)
                CurrFramePanel.Cursor = Cursors.Cross;
            else
                CurrFramePanel.Cursor = Cursors.Arrow;
        }
    }
}
